if SERVER then
	AddCSLuaFile("autorun/ecs_init.lua")
end

local function GetPluginName( str )
	local mat = string.match(str , "/(.*)%.lua*$")
	if mat then return mat end
	return string.match(str , "/(.*)")
end

ecs = {
	Selections = {},
	CommandInfo = {},
	Plugins = {},
	Meta = {},
	FOLDER = 1,
	FILE = 2,
}
ecs.Meta.__index = ecs.Meta

function ecs.Msg( str )
	MsgN("----    ",str)
end

MsgN("------------------------------------------------------------------------------")
MsgN([[
----        _________________    ____      _ __  _       ___                __
----       / ____/ ____/ ___/   /  _/___  (_) /_(_)___ _/ (_)___  ___  ____/ /
----      / __/ / /    \__ \    / // __ \/ / __/ / __ `/ / /_  / / _ \/ __  / 
----     / /___/ /___ ___/ /  _/ // / / / / /_/ / /_/ / / / / /_/  __/ /_/ /  
----    /_____/\____//____/  /___/_/ /_/_/\__/_/\__,_/_/_/ /___/\___/\__,_/   
----]])

	                                                      
function ecs.Meta:AddServerCommand( cmdname , func , auto )
	if SERVER then
		cmdname = "e_"..cmdname.."_sv"
		concommand.Add(cmdname,ecs.ProxyCommand,ecs.ProxyAutocomplete)
	else
		cmdname = "e_"..cmdname
		concommand.Add(cmdname,ecs.CallServerCommand,ecs.ProxyAutocomplete)
	end
	ecs.CommandInfo[cmdname] = {
		func = func,
		plugin = self,
		autocomplete = auto,
	}
end

function ecs.Meta:AddClientCommand( cmdname , func , auto )
	if CLIENT then
		cmdname = "e_"..cmdname
		concommand.Add(cmdname,ecs.ProxyCommand,ecs.ProxyAutocomplete)
		
		ecs.CommandInfo[cmdname] = {
			func = func,
			plugin = self,
			autocomplete = auto,
		}
	end
end


function ecs.Meta:GetSelections( ply )
	return ecs.Selections[ply] or {}
end

function ecs.Meta:AddSelection( ply , ent )
	ecs.Selections[ply] = ecs.Selections[ply] or {}
	if not ecs.CanManipulate( ply , ent ) then return end
	if table.HasValue( ecs.Selections[ply] , ent ) then return false end
	table.insert(ecs.Selections[ply],ent)
	return true
end

function ecs.Meta:AddSelections( ply , ents )
	ecs.Selections[ply] = ecs.Selections[ply] or {} 
	for k,ent in pairs(ents) do 
		if not table.HasValue( ecs.Selections[ply] , ent ) and ecs.CanManipulate( ply , ent) then 
			table.insert(ecs.Selections[ply] , ent )
		end
	end
end

function ecs.Meta:IsSelected( ply , ent )
	return table.HasValue( self:GetSelections( ply ) , ent )
end

function ecs.Meta:RemoveSelection( ply , ent )
	ecs.Selections[ply] = ecs.Selections[ply] or {} 
	local key = table.KeyFromValue( ecs.Selections[ply] , ent )
	if key then
		table.remove( ecs.Selections[ply] , key )
		return true
	end
	return false
end

function ecs.Meta:RemoveSelections( ply , ents )
	ecs.Selections[ply] = ecs.Selections[ply] or {} 
	for key , ent in pairs(ecs.Selections[ply]) do
		if table.HasValue( ents , ent ) then
			table.remove( ecs.Selections[ply] , key)
		end
	end
end

function ecs.Meta:SetSelections( ply , ents )
	for key , ent in pairs(ents) do
		if not ecs.CanManipulate( ply , ent ) then
			table.remove(ents,key)
		end
	end
	ecs.Selections[ply] = ents
end

function ecs.Meta:RemoveAllSelections( ply )
	ecs.Selections[ply] = {} 
end

function ecs.ProxyAutocomplete( cmd , args)
	local info = ecs.CommandInfo[cmd]
	local auto = info.autocomplete
	local rettab = {}
	cmd = cmd.." "
	if type(auto) == "function" then
		return info.plugin:auto( cmd , args )
	elseif type(auto) == "table" then
		for k , choices in pairs( auto ) do
			rettab[k] = cmd..choices
		end
		return rettab
	elseif type(auto) == "string" then
		return { cmd..auto }
	end
end

function ecs.ProxyCommand( ply , cmd , args )
	local info = ecs.CommandInfo[cmd]
	local plugin = info.plugin
	if args[1] == "help" then
		if type(plugin.Help) == "function" then
			plugin:Help( ply , args )
		else
			ply:PrintMessage( HUD_PRINTCONSOLE , plugin.Help )
		end
		return 
	end	
	info.func( plugin , ply , args )
end

function ecs.CallServerCommand( ply , cmd , args )
	RunConsoleCommand(cmd.."_sv",unpack(args))
end

function ecs.GetOwner( entity )
	if not IsValid(entity) then return GetWorldEntity() end
	if entity.CPPIGetOwner then
		local owner = entity:CPPIGetOwner()
		if IsValid(owner) then return owner end
	end
	return GetWorldEntity()
end

function ecs.IsOwner( ply , entity )
	return ecs.GetOwner(entity) == ply
end

function ecs.GetFriends( ply )
	if ply.CPPIGetFriends then
		return ply:CPPIGetFriends()
	end
	return {}
end

function ecs.IsFriend( owner , ply )
	if owner.CPPIGetFriends then
		for k,pl in pairs(owner:CPPIGetFriends()) do
			if pl == ply then return true end
		end
	end
	return false
end

function ecs.CanManipulate( ply , entity )
	if not IsValid( entity ) or entity:IsPlayer() or entity:IsWorld() then return false end
	if ecs.IsOwner( ply , entity ) then return true end
	if ecs.IsFriend( ecs.GetOwner(entity) , ply ) then return true end
	return false
end

function ecs.CreatePlugin()
	local cls = setmetatable({}, ecs.Meta)
	return cls
end

function ecs.LoadPlugins()
	local files , folders ,tempfile = {} , {}
	local path = "ecs_plugins/"
	local found = file.FindInLua(path.."*",true)
	for i = 1 , #found do
		tempfile = found[i]
		if tempfile != "." and tempfile != ".." then
			if string.GetExtensionFromFilename( tempfile ) == "lua" then
				files[#files + 1] = path..tempfile
			elseif !string.GetExtensionFromFilename( tempfile ) then
				folders[#folders + 1] = path..tempfile
			end
		end
	end

	for i = 1 , #files do
		tempfile = files[i]
		PLUGIN = ecs.CreatePlugin()
		PLUGIN.Name = GetPluginName(tempfile)
		PLUGIN.Directory = tempfile
		PLUGIN.__type = ecs.FILE

		ecs.Msg("Running Plugin: "..PLUGIN.Name)

		if SERVER then
			AddCSLuaFile(tempfile)
		end
		include(tempfile)

		if PLUGIN.Initialize then
			PLUGIN:Initialize()
			ecs.Plugins[ PLUGIN.Name ] = PLUGIN
		else
			ecs.Msg("No Initialize Method in "..PLUGIN.Name..", discarding plugin")
		end
		PLUGIN = nil
	end

	for i = 1 , #folders do
		tempfile = folders[i]
		PLUGIN = ecs.CreatePlugin()
		PLUGIN.Name = GetPluginName(tempfile)
		PLUGIN.Directory = tempfile
		PLUGIN.__type = ecs.FOLDER

		ecs.Msg("Running Plugin: "..PLUGIN.Name,"\t",tempfile,"\t","folder")
		include(tempfile.."/shared.lua")
		if SERVER then
			AddCSLuaFile(tempfile.."/init.lua")
			include(tempfile.."/init.lua")
		else
			include(tempfile.."/cl_init.lua")
		end	

		if PLUGIN.Initialize then
			PLUGIN:Initialize()
			ecs.Plugins[ PLUGIN.Name ] = PLUGIN
		else
			ecs.Msg("No Initialize Method in "..PLUGIN.Name..", discarding plugin")
		end
		PLUGIN = nil
	end
end
ecs.LoadPlugins()

function ecs.ReloadPlugins()
	
	for name , plugin in pairs(ecs.Plugins) do
		if plugin.__type == ecs.FILE then
			PLUGIN = ecs.CreatePlugin()
			PLUGIN.Name = name
			PLUGIN.Directory = plugin.Directory
			PLUGIN.__type = plugin.__type

			include(PLUGIN.Directory)

			if PLUGIN.Initialize then
				PLUGIN:Initialize()
				ecs.Plugins[ PLUGIN.Name ] = PLUGIN
			else
				ecs.Msg("No Initialize Method in "..PLUGIN.Name..", discarding plugin")
			end
			PLUGIN = nil
		elseif plugin.__type == ecs.FOLDER then
			PLUGIN = ecs.CreatePlugin()
			PLUGIN.Name = name
			PLUGIN.Directory = plugin.Directory
			PLUGIN.__type = plugin.__type

			include(PLUGIN.Directory.."/shared.lua")
			if SERVER then
				include(PLUGIN.Directory.."/init.lua")
			else
				include(PLUGIN.Directory.."/cl_init.lua")
			end	
			if PLUGIN.Initialize then
				PLUGIN:Initialize()
				ecs.Plugins[ PLUGIN.Name ] = PLUGIN
			else
				ecs.Msg("No Initialize Method in "..PLUGIN.Name..", discarding plugin")
			end
			PLUGIN = nil
		end
	end
end
MsgN("------------------------------------------------------------------------------")